#ifndef __virt_x2000_kenny_dkfjiwoo3w3__
#define __virt_x2000_kenny_dkfjiwoo3w3__

#include <cstdint>
#include <map>
#include <tuple>
#include <atomic>
#include <functional>
#include <thread>
#include <random>

#include <hude/base/hex.hpp>
#include <hude/utils/parses.hpp>
#include <hude/utils/json.hpp>
#include <hude/aio/context.hpp>

#include "../uhf/packet.hpp"

namespace ha
{
    namespace chr   = std::chrono;
    namespace x2000 = pgl::x2000;

    using json_t  = hude::utils::json_t;
    using clock_t = chr::system_clock;
    namespace brick
    {
        /*********************************************************************
         * @brief uhf参数设置
         */
        template< int _max >
        struct _uhf_settings_t
        {
            enum : int { emMAX_FREQ = 51, emMAX_ANTS = _max };

            uint8_t  power[ emMAX_ANTS ];  // 天线功率
            uint8_t  bund;                 // 频段
            uint8_t  epc_rate;             // EPC速率
            uint8_t  epc_qvalue;           // EPC的Q值
            uint8_t  epc_session;          // EPC的Session模式
            uint8_t  epc_target;           // EPC的盘存目标，A或B
            uint16_t time_ante;            // 天线驻留时间
            uint16_t time_freq;            // 频点驻留时间
            uint16_t filter_timeout;       // 标签上报时同一标签间隔小于该项过滤掉
            uint8_t  filter_rssi;          // 标签上报时rssi小于该项过滤掉
            bool     freqs[ emMAX_FREQ ];  // 频点开关, 第一个值为自动或手动，后继为1～50频道的开关
        };

        /*********************************************************************
         * @brief 盘点动作的参数
         */
        struct inventory_t
        {
            uint32_t ants;
            bool     keep;
            uint32_t passwd;
            struct
            {
                uint8_t        type;
                uint16_t       begin;
                hude::buffer_t match;
            } sel;

            struct
            {
                uint8_t mode;
                uint8_t lenght;
            } tid;

            struct
            {
                bool enable;
                bool force;
            } fastid;
            
        };

        /*********************************************************************
         * @brief 标签关联的天线和读取概率
         */
        struct rf_t
        {
            enum target_t : uint8_t { emTG_A = 1U, emTG_B = 2U, emTG_AB = 3U };
            enum : uint8_t { emANT_ALL = 0xffU, emPERCENT_FULL = 100U, emFREQ_DEF = 30U };

            uint8_t  ant;
            uint8_t  rand;
            uint8_t  channel;
            target_t current[4];

            std::chrono::system_clock::time_point last;

            hude::buffer_t epc, tid, buffer;
        };

        /*********************************************************************
         * @brief 标签的列表类型
         */
        using tags_t = std::list< rf_t >;

        /*********************************************************************
         * @brief 所有插件需要实现的工厂函数 
         */
        class uhf_t
        {
        public:
            enum : int { emMAX_ANTS = 4U };

            enum error_t : uint8_t
            {
                emERR_CRC   = 3U,
                emERR_MID   = 4U,
                emERR_BUSY  = 6U,
                emERR_OTHER = 10U,
            };

            using uhf_settings_t = _uhf_settings_t< emMAX_ANTS >;
            using parses_t       = hude::utils::parses_t<>;
            using on_setting_t   = std::function< hude::optional_t< hude::buffer_t >( hude::buffer_t&& buffer ) >;
            using map_settings_t = std::map< x2000::mid_t, on_setting_t >;
            using sender_t       = std::function< void( const hude::buffer_t& ) >;

        public:
            uhf_t() { init_settings(); }
            ~uhf_t() { if( busy() ) { scanning_ = false; thread_.join(); } }

            bool on_config( const json_t& );
            void on_handle( sender_t, parses_t::citr_t b, parses_t::citr_t e );

        private:
            void init_settings();
            void read( sender_t, parses_t::citr_t b, parses_t::citr_t e );
            void write( sender_t, parses_t::citr_t b, parses_t::citr_t e );
            void stop( sender_t, parses_t::citr_t b, parses_t::citr_t e );
            void inventory( sender_t, inventory_t* );

            bool idle() const { return ! thread_.joinable(); }
            bool busy() const { return thread_.joinable(); }

        private:
            uhf_settings_t   settings_, backup_;
            map_settings_t   map_settings_;
            std::thread      thread_;
            std::atomic_bool scanning_;
            tags_t           tags_;
        };

        /*********************************************************************
         * @brief ...
         */
        using void_t = hude::void_t;

        /*********************************************************************
         * @brief 配置虚拟uhf模块的策略
         */
        bool uhf_t::on_config( const json_t& cfg )
        {
            std::random_device              rd;           // 将用于为随机数引擎获得种子
            std::mt19937                    gen( rd() );  // 以播种标准 mersenne_twister_engine
            std::uniform_int_distribution<> dis( 0, 5000 );

            if( ! cfg.is_object() ) return false;

            auto itr = cfg.find( "rfid" );

            if(  itr == cfg.end() ) return false;
            if( ! itr->is_array() ) return false;

            for( const auto& item : *itr )
            {
                if( ! item.is_object() ) return false;

                auto  _id = hude::utils::json_path_t::value< std::string >( item,  "id"   );

                auto a = hude::utils::json_path_t::value_or_default< uint8_t >( item, rf_t::emANT_ALL, "ant"  );
                auto c = hude::utils::json_path_t::value_or_default< uint8_t >( item, rf_t::emPERCENT_FULL, "chl"  );
                auto r = hude::utils::json_path_t::value_or_default< uint8_t >( item, rf_t::emFREQ_DEF, "rand" );

                if( ! _id ) return false;

                auto id = hude::utils::from_hex( &((*_id)[0]), (*_id).size() );
                if( ! id ) return false;

                clock_t::time_point last = clock_t::now() - chr::milliseconds( dis( gen ) );

                auto buffer = x2000::pkt_evt_t< x2000::mid_t::emREAD_TAG >::type_t{ &((*id)[0]), (*id).size(), a }.to_buffer();

                tags_.push_back( rf_t{ a, r, c,
                    { rf_t::emTG_A, rf_t::emTG_A, rf_t::emTG_A, rf_t::emTG_A },
                    last, *id, *id, buffer } );
            }

            return true;
        }

        /*********************************************************************
         * @brief 处理uhf请求返回
         */
        void uhf_t::on_handle( sender_t sender, parses_t::citr_t b, parses_t::citr_t e )
        {
            if( b == e ) return;

            b += 1;

            auto h = (const x2000::packet_t*)&( *( b ) );

            const uint8_t state = ( this->busy() )? 1U : 2U;

            if( ! h->check( h->lenght() ) )
            {
                llog_err( "<plug-x2000>", "ERROR: packet CRC error: %s", hude::utils::to_hex( &*b, e - b ).c_str() );

                sender( x2000::packet_err_t{ emERR_CRC, state, *h }.to_buffer() );

                return;
            }

            if( h->mid() == (uint8_t)x2000::mid_t::emSTOP )
            {
                this->stop( sender, b, e );
            }
            else

            if( h->mid() == (uint8_t)x2000::mid_t::emWRITE )
            {
                this->write( sender, b, e );
            }
            else

            if( h->mid() == (uint8_t)x2000::mid_t::emREAD )
            {
                this->read( sender, b, e );
            }
            else
            {
                auto itr = map_settings_.find( (x2000::mid_t)( h->head.message ) );

                if( itr != map_settings_.end() )
                {
                    // 如果是查询类指令或工作状态为空闲时可执行
                    if( ( h->head.message & 0x01 ) == 0 || h->head.message == 0xe1 || this->idle() )
                    {
                        auto ret = itr->second( hude::buffer_t{ b, e } );

                        if( ret ) sender( *ret );
                    } else {
                        sender( x2000::packet_err_t{ emERR_BUSY, state, *h }.to_buffer() );
                    }

                    return;
                }

                llog_war( "<plug-x2000>", "Not support message id: %#x", h->head.message );

                sender( x2000::packet_err_t{ emERR_MID, state, *h }.to_buffer() );
            }
        }

        /*********************************************************************
         * @brief 生成返回结果
         */
        template< x2000::mid_t _mid >
        inline hude::optional_t< hude::buffer_t > fres( uint8_t ret )
        {
            typename x2000::pkt_res_t< _mid >::type_t pkg{ ret };
            return pkg.to_buffer();
        }

        /*********************************************************************
         * @brief 添加设置项
         */
        void uhf_t::init_settings()
        {
            memset( &settings_, 0, sizeof( uhf_settings_t ) );

            settings_ = uhf_settings_t{ { 30U, 30U, 30U, 30U }, 3U, 0U, 0U, 0U,  0U, 5U, 1U, 0U };

            //---------------------------------------------
            // 天线功率
            {
                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emSET_POWER, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emSET_POWER." );

                    using req_t = x2000::pkt_req_t< x2000::mid_t::emSET_POWER >::type_t;

                    auto f = (const req_t*)&(frame[0]);

                    auto b = (const x2000::argument_t< uint8_t >*)(f->body);

                    int count = (frame.size() - x2000::packet_t::emSIZ_HEAD - x2000::packet_t::emSIZ_CRC);
                    if( count == 0 || count & 0x01 ) return fres< x2000::mid_t::emSET_POWER >( 1 );

                    auto p = b;

                    count = count / 2;

                    for( ; p != b + count; ++p )
                    {
                        if( p->pid == 0xff )
                        {
                            memcpy( this->backup_.power, this->settings_.power, req_t::emANT_COUNT );

                            break;
                        }

                        if( p->pid == 0 || p->pid > req_t::emANT_COUNT )
                        {
                            llog_err( "<plug-x2000>", "ERROR: antenna number: %u, not 1 to N.", p->pid );
                            return fres< x2000::mid_t::emSET_POWER >( 1 );
                        }

                        if( p->value > 33U )
                        {
                            llog_err( "<plug-x2000>", "ERROR: power too big: %u", p->value );
                            return fres< x2000::mid_t::emSET_POWER >( 2 );
                        }

                        this->settings_.power[p->pid - 1] = p->value;
                    }

                    return fres< x2000::mid_t::emSET_POWER >( 0 );
                } );

                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emGET_POWER, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emGET_POWER." );

                    using pkt_t = x2000::pkt_res_t< x2000::mid_t::emGET_POWER >::type_t;

                    pkt_t pkt;

                    for( uint8_t i = 0; i < uhf_settings_t::emMAX_ANTS; ++i )
                    {
                        pkt.body[i * 2 + 0] = i + 1;
                        pkt.body[i * 2 + 1] = this->settings_.power[i];
                    }

                    pkt.set_crc( pkt_t::emBODY );

                    return pkt.to_buffer();
                } );
            }

            //---------------------------------------------
            // 工作频段
            {
                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emSET_RF_BAND, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emSET_RF_BAND." );

                    using req_t = x2000::pkt_req_t< x2000::mid_t::emSET_RF_BAND >::type_t;

                    auto f = (const req_t*)&(frame[0]);

                    if( f->body[0] > 8U )
                    {
                        llog_err( "<plug-x2000>", "ERROR: Not support RF band: %u", f->body[0] );
                        return fres< x2000::mid_t::emSET_RF_BAND >( 1 );
                    }

                    this->settings_.bund = f->body[0];

                    if( f->body[1] == 0x01 )
                    {
                        this->backup_.bund = f->body[0];
                    }

                    return fres< x2000::mid_t::emSET_RF_BAND >( 0 );
                } );

                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emGET_RF_BAND, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emGET_RF_BAND." );

                    using pkt_t = x2000::pkt_res_t< x2000::mid_t::emGET_RF_BAND >::type_t;

                    pkt_t pkt;

                    pkt.result( this->settings_.bund );

                    pkt.set_crc( pkt_t::emBODY );

                    return pkt.to_buffer();
                } );
            }

            //---------------------------------------------
            // 工作频点
            {
                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emSET_RF_FREQ, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emSET_RF_FREQ." );

                    using req_t = x2000::pkt_req_t< x2000::mid_t::emSET_RF_FREQ >::type_t;

                    auto f = (const req_t*)&(frame[0]);

                    if( f->body[0] > 1U ) // 0 or 1
                    {
                        llog_err( "<plug-x2000>", "ERROR: Auto freq setting invaild." );
                        return fres< x2000::mid_t::emSET_RF_FREQ >( 3 );
                    } else {
                        this->settings_.freqs[0] = ( f->body[0] != 0 );
                    }

                    auto p = f->body + 1;

                    if( *p == 1U )
                    {
                        if( f->body[0] == 1U )
                        {
                            llog_err( "<plug-x2000>", "ERROR: Invaild item of RF freq list, current auto freqs." );
                            return fres< x2000::mid_t::emSET_RF_FREQ >( 1 );
                        }

                        auto count = x2000::_value_t< uint16_t >::get( p + 1 );

                        for( int i = 1; i < uhf_settings_t::emMAX_FREQ; ++i )
                        {
                            this->settings_.freqs[i] = false;
                        }

                        p += 3;

                        for( const uint8_t* v = p; v < p + count; ++v )
                        {
                            if( *v == 0 || *v >= uhf_settings_t::emMAX_FREQ )
                            {
                                llog_err( "<plug-x2000>", "ERROR: Invaild item of RF freq list: %u", *v );
                                return fres< x2000::mid_t::emSET_RF_FREQ >( 1 );
                            }

                            this->settings_.freqs[*v] = true;
                        }

                        p += count;
                    }

                    if( *p == 2U ) // save flag
                    {
                        p += 1;

                        if( *p > 1 ) // 0 or 1
                        {
                            llog_err( "<plug-x2000>", "ERROR: Save flag invaild: %u", *p );
                            return fres< x2000::mid_t::emSET_RF_FREQ >( 3 );
                        }
                    }

                    return fres< x2000::mid_t::emSET_RF_FREQ >( 0 );
                } );

                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emGET_RF_FREQ, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emGET_RF_FREQ." );

                    using pkt_t = x2000::pkt_res_t< x2000::mid_t::emGET_RF_FREQ >::type_t;

                    pkt_t pkt;

                    if( this->settings_.freqs[0] )
                    {
                        pkt.body[0] = 1U;
                        pkt.body[1] = 0U;

                        pkt.set_crc( 2U );
                    } else {
                        pkt.body[0] = 0U;
                        pkt.body[1] = 0U;

                        for( uint8_t i = 1; i < uhf_settings_t::emMAX_FREQ; ++i )
                        {
                            if( this->settings_.freqs[i] )
                            {
                                pkt.body[2 + pkt.body[1]] = i;
                                pkt.body[1] += 1;
                            }
                        }

                        pkt.lenght( 2 + pkt.body[1] );

                        pkt.set_crc( 2 + pkt.body[1] );
                    }

                    return pkt.to_buffer();
                } );
            }

            //---------------------------------------------
            // 标签上报参数
            {
                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emSET_TAG, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emSET_TAG." );

                    using req_t = x2000::pkt_req_t< x2000::mid_t::emSET_TAG >::type_t;

                    auto f = (const req_t*)&(frame[0]);

                    auto p = f->body;

                    if( *p == 1U )
                    {
                        this->settings_.filter_timeout = x2000::_value_t< uint16_t >::get( p + 1 );
                        p += 3;
                    }

                    if( *p == 2U )
                    {
                        this->settings_.filter_rssi = *( p + 1 );
                        p += 2;
                    }

                    return fres< x2000::mid_t::emSET_TAG >( (p == f->body)? 1 : 0 );
                } );

                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emGET_TAG, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emGET_TAG." );

                    using pkt_t = x2000::pkt_res_t< x2000::mid_t::emGET_TAG >::type_t;

                    pkt_t pkt;

                    pkt.time( this->settings_.filter_timeout );
                    pkt.rssi( this->settings_.filter_rssi );

                    pkt.set_crc( pkt_t::emBODY );

                    return pkt.to_buffer();
                } );
            }

            //---------------------------------------------
            // EPC基带参数
            {
                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emSET_EPC, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emSET_EPC." );

                    using req_t = x2000::pkt_req_t< x2000::mid_t::emSET_EPC >::type_t;

                    auto f = (const req_t*)&(frame[0]);
                    auto s = ( frame.size() - x2000::packet_t::emSIZ_HEAD - x2000::packet_t::emSIZ_CRC ) / 2;

                    if( s == 0 || s > 4U )
                    {
                        llog_err( "<plug-x2000>", "ERROR: Invaild frame size.:" );
                        return fres< x2000::mid_t::emSET_EPC >( 5 );
                    }

                    auto a = (const x2000::argument_t< uint8_t >*)(f->body);

                    for( auto p = a; p < a + s; ++p )
                    {
                        if( p->pid == 1U )
                        {
                            if( p->value > 4 && p->value < 255 )
                            {
                                llog_err( "<plug-x2000>", "ERROR: Invaild EPC band rate: %u", p->value );
                                return fres< x2000::mid_t::emSET_EPC >( 1 );
                            }

                            this->settings_.epc_rate = p->value;
                        }
                        else if( p->pid == 2U )
                        {
                            if( p->value > 15U )
                            {
                                llog_err( "<plug-x2000>", "ERROR: Invaild EPC Q value: %u", p->value );
                                return fres< x2000::mid_t::emSET_EPC >( 2 );
                            }

                            this->settings_.epc_qvalue = p->value;
                        }
                        else if( p->pid == 3U )
                        {
                            if( p->value > 3U )
                            {
                                llog_err( "<plug-x2000>", "ERROR: Invaild EPC session: %u", p->value );
                                return fres< x2000::mid_t::emSET_EPC >( 3 );
                            }

                            this->settings_.epc_session = p->value;
                        }
                        else if( p->pid == 4U )
                        {
                            if( p->value > 2U )
                            {
                                llog_err( "<plug-x2000>", "ERROR: Invaild EPC target %u, rang: 0(A) or 1(B) or 2(A|B).", p->value );
                                return fres< x2000::mid_t::emSET_EPC >( 4 );
                            }

                            this->settings_.epc_target = p->value;
                        }
                        else if( p->pid == 0xff )
                        {
                            if( p->value )
                            {
                                this->backup_.epc_rate    = this->settings_.epc_rate;
                                this->backup_.epc_qvalue  = this->settings_.epc_qvalue;
                                this->backup_.epc_session = this->settings_.epc_session;
                                this->backup_.epc_target  = this->settings_.epc_target;
                            }
                        }
                        else
                        {
                            llog_err( "<plug-x2000>", "ERROR: Not support PID: %u", p->pid );
                            return fres< x2000::mid_t::emSET_EPC >( 5 );
                        }
                    }

                    return fres< x2000::mid_t::emSET_EPC >( 0 );
                } );

                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emGET_EPC, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emGET_EPC." );

                    using pkt_t = x2000::pkt_res_t< x2000::mid_t::emGET_EPC >::type_t;

                    pkt_t pkt;

                    pkt.speed( this->settings_.epc_rate );
                    pkt.qv( this->settings_.epc_qvalue );
                    pkt.session( this->settings_.epc_session );
                    pkt.target( this->settings_.epc_target );

                    pkt.set_crc( pkt_t::emBODY );

                    return pkt.to_buffer();
                } );
            }

            //---------------------------------------------
            // 驻留时间
            {
                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emSET_HOLD, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emSET_HOLD." );

                    using req_t = x2000::pkt_req_t< x2000::mid_t::emSET_HOLD >::type_t;

                    auto f = (const req_t*)&(frame[0]);

                    const uint8_t* p = f->body;

                    if( *p == 1U )
                    {
                        this->settings_.time_ante = x2000::_value_t<uint16_t>::get( ++p );
                        p += 2;
                    }

                    if( *p == 2U )
                    {
                        this->settings_.time_freq = x2000::_value_t<uint16_t>::get( ++p );
                        p += 2;
                    }

                    if( *p == 0xff )
                    {
                        if( *(++p) != 0 )
                        {
                            this->backup_.time_ante = this->settings_.time_ante;
                            this->backup_.time_freq = this->settings_.time_freq;
                        }
                    }

                    return fres< x2000::mid_t::emSET_HOLD >( 0 );
                } );

                //---------------------------------------------
                map_settings_.emplace( x2000::mid_t::emGET_HOLD, [=]( hude::buffer_t&& frame )
                {
                    llog_dug( "<plug-x2000>", "\t<UHF> emGET_HOLD." );

                    using pkt_t = x2000::pkt_res_t< x2000::mid_t::emGET_HOLD >::type_t;

                    pkt_t pkt;

                    pkt.ant( this->settings_.time_ante );
                    pkt.freq( this->settings_.time_freq );

                    pkt.set_crc( pkt_t::emBODY );

                    return pkt.to_buffer();
                } );
            }
        }

        /*********************************************************************
         * @brief 结束读标签
         */
        inline void uhf_t::stop( sender_t sender, parses_t::citr_t b, parses_t::citr_t e )
        {
            llog_dug( "<plug-x2000>", "\t<UHF> emSTOP." );

            if( this->busy() )
            {
                this->scanning_ = false;
                this->thread_.join();
            }

            sender( x2000::pkt_res_t< x2000::mid_t::emSTOP >::type_t{ 0U }.to_buffer() );
        }

        /*********************************************************************
         * @brief 写标签
         */
        inline void uhf_t::write( sender_t sender, parses_t::citr_t b, parses_t::citr_t e )
        {
            llog_dug( "<plug-x2000>", "\t<UHF> emWRITE." );

            using req_t = x2000::pkt_req_t< x2000::mid_t::emREAD >::type_t;
            using res_t = x2000::pkt_res_t< x2000::mid_t::emWRITE >::type_t;

            enum : uint8_t {  emRUNNING = 1U };

            auto frame = &*b;
            auto fend = &*e;

            auto f = (const req_t*)&(frame[0]);

            if( this->busy() )
            {
                sender( x2000::packet_err_t{ emERR_BUSY, emRUNNING, *f }.to_buffer() );
                return;
            }

            auto p = f->body;

            //-----------------------------------
            // 天线
            auto ants = x2000::_value_t< uint32_t >::get( p );  p += 4;

            if( ants == 0U )
            {
                sender( res_t{ 1U, 0U }.to_buffer() );
                return;
            }

            //-----------------------------------
            // 写入的数据区
            auto pos = *(p++);

            if( pos > 3U )
            {
                sender( res_t{ 3U, 0U }.to_buffer() );
                return;
            }

            // 写入的地址
            // auto addr = x2000::_value_t< uint16_t >::get( p );
            p += 2;

            // 写入的长度
            auto siz = x2000::_value_t< uint16_t >::get( p );  p += 2;

            if( p + siz >= fend )
            {
                sender( res_t{ 3U, 0U }.to_buffer() );
                return;
            }

            // 写入的内容
            hude::buffer_t dat{ p, p + siz };  p += siz;

            if( dat.empty() )
            {
                sender( res_t{ 3U, 0U }.to_buffer() );
                return;
            }

            //-----------------------------------
            // 筛选标签
            uint8_t mpos = 0U;
            uint8_t msiz = 0U;
            uint16_t maddr = 0U;
            hude::buffer_t mdat;

            if( *(p++) == 0x01 )
            {
                // 筛选的数据区
                mpos = *(p++);

                if( mpos > 3U )
                {
                    sender( res_t{ 2U, 0U }.to_buffer() );
                    return;
                }

                // 筛选的地址
                maddr = x2000::_value_t< uint16_t >::get( p );  p += 2;

                // 筛选的长度
                msiz = *(p++);

                // 筛选的内容
                mdat.assign( p, p + msiz );  p += msiz;
            }

            //-----------------------------------
            // 访问密码
            // uint32_t pwd = 0U;

            // if( *(p++) == 0x02 )
            // {
            //     pwd = x2000::_value_t< uint32_t >::get( p );  p += 4;
            // }

            //-----------------------------------
            // 写标签
            auto eq = []( const hude::buffer_t& m, const hude::buffer_t& t, uint16_t o ) -> bool
            {
                if( ( t.size() - o ) < m.size() ) return false;

                for( size_t i = 0; i < m.size(); ++i )
                {
                    if( m[i] != t[i + o] ) return false;
                }

                return true;
            };

            // 写入所有符合的标签
            for( auto& r : this->tags_ )
            {
                if( 0U == ( ants & ( 1 << r.ant ) ) ) continue;

                if( ! mdat.empty() )
                {
                    if( mpos == 1U && ! eq( mdat, r.epc, maddr ) ) continue;
                    if( mpos == 2U && ! eq( mdat, r.tid, maddr ) ) continue;
                }

                // auto  = hude::utils::to_hex( dat, 0, 0 );
                // if( pos == 1U ) r.epc.assign = hude::utils::to_hex( dat, 0, 0 );

                if( pos == 1U ) { std::swap( r.epc, dat ); }
                if( pos == 2U ) { std::swap( r.tid, dat ); }

                r.buffer = x2000::pkt_evt_t< x2000::mid_t::emREAD_TAG >::type_t{ &((r.epc)[0]), r.epc.size(), r.ant }.to_buffer();
            }

            //-----------------------------------
            sender( res_t{ 0U, 0U }.to_buffer() );
        }

        /*********************************************************************
         * @brief 开始读标签
         */
        inline void uhf_t::read( sender_t sender, parses_t::citr_t b, parses_t::citr_t e )
        {
            llog_dug( "<plug-x2000>", "\t<UHF> emREAD." );

            using req_t = x2000::pkt_req_t< x2000::mid_t::emREAD >::type_t;

            enum : uint8_t {  emRUNNING = 1U };

            auto frame = &*b;

            auto f = (const req_t*)&(frame[0]);

            if( this->busy() )
            {
                sender( x2000::packet_err_t{ emERR_BUSY, emRUNNING, *f }.to_buffer() );
                sender( x2000::pkt_res_t< x2000::mid_t::emREAD >::type_t{ 2 }.to_buffer() );
                return;
            }

            const uint8_t* p = f->body;

            auto args = new inventory_t;

            args->ants = x2000::_value_t< uint32_t >::get( p );
            p += sizeof( uint32_t );

            args->keep = *p;
            p += 1;

            if( *p == 1U )
            {
                args->sel.type = *(++p);
                args->sel.begin = x2000::_value_t< uint16_t >::get( p );
                p += 2;
                auto s = *(++p);

                if( s )
                {
                    args->sel.match.assign( p, p + s );

                    p += s;
                }
            } else {
                args->sel.type = 0xff;
            }

            if( *p == 2U )
            {
                args->tid.mode = *(++p);
                args->tid.lenght = *(++p);
                p += 1;
            } else {
                args->tid.mode = 0xff;
            }

            if( *p == 5U )
            {
                args->passwd = x2000::_value_t<uint32_t >::get( ++p );
                p += 4;
            }

            if( *p == 0x0a )
            {
                args->fastid.enable = ( (*(++p))? true : false );
                args->fastid.force  = ( (*(++p))? true : false );
                p += 1;
            }

            this->thread_ = std::thread{ std::bind( &uhf_t::inventory, this, sender, args ) };

            sender( x2000::pkt_res_t< x2000::mid_t::emREAD >::type_t{ 0 }.to_buffer() );
        }

        /*********************************************************************
         * @brief 盘存过程
         */
        void uhf_t::inventory( sender_t sender, inventory_t* args )
        {
            std::random_device              rd;           // 将用于为随机数引擎获得种子
            std::mt19937                    gen( rd() );  // 以播种标准 mersenne_twister_engine
            std::uniform_int_distribution<> dis( 2000, 5000 );

            using ctx_t = hude::aio::context_t<>;

            std::unique_ptr< inventory_t > _ptr( args );  //自动释放内存

            auto inants = [=]() -> std::map< uint8_t, int >
            {
                std::map< uint8_t, int > _ants;

                for( auto& r : this->tags_ )
                {
                    _ants.emplace( r.ant, 0 );
                }

                return  _ants;
            };

            auto tags = [&]( sender_t sender, uhf_t* thiz, uint8_t ant, uint8_t chl, size_t times )
            {
                const uint8_t             a = rf_t::emANT_ALL;
                const uint8_t             f = rf_t::emPERCENT_FULL;
                const chr::milliseconds   t{ thiz->settings_.filter_timeout * 10U };
                const clock_t::time_point now = clock_t::now();
                const uint8_t             tg  = thiz->settings_.epc_target + 1;

                for( auto& r : thiz->tags_ )
                {
                    auto& current = r.current[thiz->settings_.epc_session & 0x03];

                    // 天线匹配
                    if ( r.ant != ant && r.ant != a ) continue;
                    // 频点匹配
                    if ( std::abs( r.channel - chl ) > 1 ) continue;
                    // 读取概率
                    if ( ( times % f ) >= r.rand ) continue;
                    // 读取间隔
                    if ( thiz->settings_.filter_timeout != 0 && now < ( r.last + t ) ) continue;
                    // 读取目标状态
                    if ( !( tg & current ) ) continue;

                    current = ( current == rf_t::emTG_A )? rf_t::emTG_B : rf_t::emTG_A;

                    // 更新最后一次读取时间点
                    r.last = now + chr::milliseconds( dis( gen ) );

                    llog_dug( "<plug-x2000>", "\t<UHF> EVENT TAG." );

                    // 发送读取标签事件
                    sender( r.buffer );
                }
            };

            auto scan = [=]( sender_t sender, size_t index, uint8_t& ant_last )
            {
                // 频点或天线驻留的时间单位是10微秒
                uint16_t hold = ( (this->settings_.freqs[0])? this->settings_.time_freq : this->settings_.time_ante );

                const auto _inants = inants();

                // 循环天线
                for( uint8_t idx_ant = 0; idx_ant < uhf_settings_t::emMAX_ANTS && this->scanning_; ++idx_ant )
                {
                    // idx_nat对应天线未使用
                    {
                        auto mask = (1U << idx_ant);

                        if( 0 == ( mask & args->ants ) ) continue;
                    }

                    // 发送天线设置通知
                    if( ant_last != idx_ant )
                    {
                        ant_last = idx_ant;

                        sender( x2000::pkt_evt_t< x2000::mid_t::emREAD_ANT >::type_t{ idx_ant }.to_buffer() );
                    }

                    // 如果该天线没有标签可读
                    if( _inants.find( idx_ant ) == _inants.end() && hold )
                    {
                        std::this_thread::sleep_for( std::chrono::milliseconds{ hold * uhf_settings_t::emMAX_FREQ } );
                    }

                    if( this->settings_.freqs[0] )
                    {
                        // 循环设定的频点列表
                        for( uint8_t idx_frq = 0; idx_frq < uhf_settings_t::emMAX_FREQ && this->scanning_; ++idx_frq )
                        {
                            if( ! this->settings_.freqs[idx_frq] ) continue;

                            tags( sender, this, idx_ant, idx_frq, index );

                            if( hold ) std::this_thread::sleep_for( std::chrono::milliseconds{ hold } );
                        }
                    } else {
                        // 循环所有频点
                        for( uint8_t idx_chl = 0; idx_chl < uhf_settings_t::emMAX_FREQ && this->scanning_; ++idx_chl )
                        {
                            tags( sender, this, idx_ant, idx_chl, index );

                            if( hold ) std::this_thread::sleep_for( std::chrono::milliseconds{ hold } );
                        }
                    }
                }
            };

            auto cb_target_reset = []( ctx_t::tasks_t::id_t, uintptr_t user )
            {
                auto thiz = (uhf_t*)user;

                const clock_t::time_point now = clock_t::now();

                for( auto& r : thiz->tags_ )
                {
                    if( r.last < now + std::chrono::milliseconds( 2000U ) )
                    {
                        r.current[0] = rf_t::emTG_A;
                        r.current[2] = rf_t::emTG_A;
                        r.current[3] = rf_t::emTG_A;
                    }
                }
            };

            this->scanning_ = true;

            size_t index = 0;
            uint8_t ant_last = 0xff;

            // 定时恢复盘存状态的
            auto aio = ctx_t::aio();
            auto tid = aio->task_genid();
            aio->task_commit( tid, ctx_t::tasks_t::emTYPE_CYCLICITY, ctx_t::tasks_t::interval_t( 200U ),
                cb_target_reset, (uintptr_t)(void*)this );

            // 模拟盘存
            do
            {
                llog_tra("<plug-x2000>", "begin a times inventory.");

                scan( sender, index, ant_last );

                index += 1;

            } while( args->keep && this->scanning_ );

            aio->task_remove( tid );

            this->scanning_ = false;

            // 发送盘点结束通知
            {
                uint8_t type = ( args->keep )? 1U : 0U;
                sender( x2000::pkt_evt_t< x2000::mid_t::emREAD_END >::type_t{ type }.to_buffer() );
            }
        }
    } //namespace brick
} //namespace ha

#endif  //__virt_x2000_kenny_dkfjiwoo3w3__
